package com.leyou.item.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.leyou.common.dto.CartDTO;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.vo.PageResult;
import com.leyou.item.mapper.GoodsMapper;
import com.leyou.item.mapper.SkuMapper;
import com.leyou.item.mapper.SpuDetailMapper;
import com.leyou.item.mapper.StockMapper;
import com.leyou.item.pojo.*;
import com.leyou.item.service.GoodsService;
import com.leyou.item.service.IBrandService;
import com.leyou.item.service.ICategoryService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class GoodsServiceImpl implements GoodsService {


    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private SpuDetailMapper spuDetailMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private StockMapper stockMapper;

    @Autowired
    private IBrandService brandService;

    @Autowired
    private ICategoryService categoryService;


    @Override
    public PageResult<SpuBo> querySpuPage(String key, Integer page, Integer rows, Boolean saleable) {

        PageHelper.startPage(page, rows);

        Example example = new Example(SpuBo.class);

        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(key)) {
            criteria.andLike("title", "%" + key + "%");
        }

        if (saleable != null) {
            criteria.andEqualTo("saleable", saleable);
        }

        criteria.andEqualTo("valid", true);

        example.setOrderByClause("last_update_time DESC");

        List<SpuBo> spuVoList = goodsMapper.selectByExample(example);

        if (CollectionUtils.isEmpty(spuVoList)) {
            throw new LyException(ExceptionEnum.QUERY_SPU_ERROR);
        }

        HandlerCnameAndBname(spuVoList);

        PageInfo<SpuBo> info = new PageInfo<>(spuVoList);

        return new PageResult<>(info.getTotal(), info.getList());
    }

    /**
     * 保存商品信息
     *
     * @param spuBo
     */
    @Override
    @Transactional
    public void saveGood(SpuBo spuBo) {

        // 保存spu
        spuBo.setSaleable(true);
        spuBo.setValid(true);
        spuBo.setCreateTime(new Date());
        spuBo.setLastUpdateTime(spuBo.getCreateTime());
        int count = goodsMapper.insert(spuBo);
        if (count != 1) {
            throw new LyException(ExceptionEnum.INTERNAL_SERVER_ERROR);
        }

        // 保存spu详情
        spuBo.getSpuDetail().setSpuId(spuBo.getId());
        count = spuDetailMapper.insert(spuBo.getSpuDetail());
        if (count != 1) {
            throw new LyException(ExceptionEnum.INTERNAL_SERVER_ERROR);
        }

        // 保存sku和库存信息
        saveSkuAndStock(spuBo.getSkus(), spuBo.getId());
    }

    /**
     * 根据spuid查询spu详情数据
     *
     * @param spuId
     * @return
     */
    @Override
    public SpuDetail querySpuDetailBySpuId(Long spuId) {
        SpuDetail spuDetail = spuDetailMapper.selectByPrimaryKey(spuId);
        if (spuDetail == null) {
            throw new LyException(ExceptionEnum.QUERY_SPU_DETAIL_NOT_FOUND);
        }
        return spuDetail;
    }

    /**
     * 根据spuid查询sku集合数据
     *
     * @param spuId
     * @return
     */
    @Override
    public List<Sku> querySkuBySpuId(Long spuId) {
        // 查询sku
        Sku sku = new Sku();
        sku.setSpuId(spuId);
        List<Sku> skuList = skuMapper.select(sku);
        if (CollectionUtils.isEmpty(skuList)) {
            throw new LyException(ExceptionEnum.QUERY_SKU_NOT_FOUND);
        }

        // 填充库存
        fillSkuStock(skuList);

        return skuList;
    }

    /**
     * 修改商品数据
     *
     * @param spuBo
     */
    @Override
    @Transactional
    public void updateGood(SpuBo spuBo) {
        if (spuBo.getId() == null) {
            throw new LyException(ExceptionEnum.GOOD_ID_NOT_EMPTY);
        }
        // 先查询以前的sku
        Sku sku = new Sku();
        sku.setSpuId(spuBo.getId());
        // 查询sku
        List<Sku> skus = skuMapper.select(sku);

        if (CollectionUtils.isNotEmpty(skus)) {
            // 存在,则删除sku
            skuMapper.delete(sku);
            // 删除库存
            List<Long> ids = skus.stream().map(Sku::getId).collect(Collectors.toList());
            int count = stockMapper.deleteByIdList(ids);
        }

        // 修改spu
        spuBo.setLastUpdateTime(new Date());
        spuBo.setValid(null);
        spuBo.setSaleable(null);
        spuBo.setCreateTime(null);
        int count = goodsMapper.updateByPrimaryKeySelective(spuBo);
        if (count != 1) {
            throw new LyException(ExceptionEnum.INTERNAL_SERVER_ERROR);
        }
        // 修改detail
        count = spuDetailMapper.updateByPrimaryKeySelective(spuBo.getSpuDetail());
        if (count != 1) {
            throw new LyException(ExceptionEnum.INTERNAL_SERVER_ERROR);
        }

        // 新增sku和库存
        saveSkuAndStock(spuBo.getSkus(), spuBo.getId());

        // 发送消息
        amqpTemplate.convertAndSend("item.update", spuBo.getId());
    }

    @Override
    public SpuBo querySpuBySpuId(Long spuId) {
        SpuBo spuBo = goodsMapper.selectByPrimaryKey(spuId);
        if (spuBo == null) {
            throw new LyException(ExceptionEnum.QUERY_SPU_ERROR);
        }

        List<Sku> skus = querySkuBySpuId(spuId);
        spuBo.setSkus(skus);

        SpuDetail spuDetail = querySpuDetailBySpuId(spuId);
        spuBo.setSpuDetail(spuDetail);
        return spuBo;
    }

    @Override
    public List<Sku> querySkuBySkuIds(List<Long> skuIds) {

        List<Sku> skus = skuMapper.selectByIdList(skuIds);
        if (CollectionUtils.isEmpty(skus)) {
            throw new LyException(ExceptionEnum.QUERY_SKU_NOT_FOUND);
        }
        // 填充库存
        fillSkuStock(skus);


        return skus;
    }

    @Override
    @Transactional
    public void decreaseStock(List<CartDTO> cartDTOList) {
        for (CartDTO cartDTO : cartDTOList) {

            int count = stockMapper.updateStock(cartDTO.getSkuId(), cartDTO.getNum());
            if (count != 1) {
                throw new LyException(ExceptionEnum.STOCK_NOT_ENOUGH_ERROR);
            }
        }
    }

    private void fillSkuStock(List<Sku> skus) {
        // 查询库存
        for (Sku sku1 : skus) {
            Stock stock = stockMapper.selectByPrimaryKey(sku1.getId());
            if (stock == null) {
                throw new LyException(ExceptionEnum.INTERNAL_SERVER_ERROR);
            }
            sku1.setStock(stock.getStock());
        }
    }

    /**
     * 自定义方法
     * 保存sku和stock
     *
     * @param skus
     * @param spuId
     */
    private void saveSkuAndStock(List<Sku> skus, Long spuId) {

        List<Stock> stocks = new ArrayList<>();
        // 新增sku
        for (Sku sku : skus) {
            sku.setSpuId(spuId);
            sku.setCreateTime(new Date());
            sku.setLastUpdateTime(sku.getCreateTime());
            int count = skuMapper.insert(sku);

            if (count != 1) {
                throw new LyException(ExceptionEnum.INTERNAL_SERVER_ERROR);
            }

            // 生成stock
            Stock stock = new Stock();
            stock.setSkuId(sku.getId());
            stock.setStock(sku.getStock());
            stocks.add(stock);
        }

        // 批量新增库存
        int count = stockMapper.insertList(stocks);
        if (count != stocks.size()) {
            throw new LyException(ExceptionEnum.INTERNAL_SERVER_ERROR);
        }

        // 发送消息
        amqpTemplate.convertAndSend("item.insert", spuId);

    }


    private void HandlerCnameAndBname(List<SpuBo> spuVoList) {

        for (SpuBo spuBo : spuVoList) {

            spuBo.setBname(brandService.queryBrandById(spuBo.getBrandId()).getName());

            List<Category> categoryList = categoryService.queryByIds(Arrays.asList(spuBo.getCid1(), spuBo.getCid2(), spuBo.getCid3()));

            spuBo.setCname(StringUtils.join(categoryList.stream().map(Category::getName).collect(Collectors.toList()), "/"));
        }
    }
}
